
/**
 * 
 * @param fn 被执行防抖操作的函数
 * @param delay 防抖多少毫秒
 */
function debounce(fn: Function, delay: number) {
    let timer: number;
    return function (...args: any[]) {
        clearTimeout(timer);
        let context: any = this;
        timer = setTimeout(() => {
            // 如果这里不是箭头函数，是一般函数，必须设置context,因为不设置context就为window
            fn.apply(context, args);
        }, delay)
    }
}

/**
 * 节流函数
 * @param fn 被节流的函数 
 * @param delay 节流间隔时间，单位毫秒
 */
function throttle(fn: Function, delay: number) {
    let last: number = +new Date();
    // 定时器
    let timer: number;
    return function (...args: any[]) {
        clearTimeout(timer);
        let now: number = +new Date();
        if (now - last >= delay) {
            fn.apply(this, args);
            last = now;
        } else {
            timer = setTimeout(() => {
                fn.apply(this, args);
                last = now;
            })
        }
    }
}

/**
 * 简单的深拷贝。存在问题，如果js 属性在JSON中没有找到对象类型，它的值将为null(如NaN、Infinity)。undefined，将丢失这个属性（如function）
 * @param o 要被深拷贝的对象
 */
function easyDeepClone(o: any) {
    // 不能深拷贝function
    return JSON.parse(JSON.stringify(o));
}

function deepClone(o: any) {
    throw new Error('can not use this method. Because it has not been implement!!!');
}
/**
 * todo 待测试。这是浏览器环境下面的ajax请求,返回类型是json
 * @param url 
 * @param type 
 * @param params 
 * @param isAsync 
 * @param successCallback 
 * @param failCallback 
 */
function ajax(url: string, type: string, params: any, isAsync: boolean = true, successCallback: Function, failCallback: Function) {
    // todo r的获取需要处理一下
    let r = new XMLHttpRequest();
    // 在调用open方法之前定义onreadystatechange才能保证兼容性
    r.onreadystatechange = () => {
        if (r.readyState == 4) {
            if ((r.status >= 200 && r.status < 300) || r.status == 304) {
                // 请求成功的回调函数
                successCallback(r.responseText);
            } else {
                failCallback(r.status);
            }
        }
    }
    // 这不是真正发送请求，而是启动一个请求以备发送
    r.open(url, type, isAsync);
    // 让服务器返回类型为json
    r.setRequestHeader('dataType', 'json');
    r.setRequestHeader('contentType', 'application/json;charset=utf-8')
    if (type === 'post') {
        r.send(params);
    }
    r.send(null);
}

/**
 * 给字符串，从尾部开始，每三位添加一个符号
 * @param num 
 * @param mark 需要添加的符号
 */
function addMark(num: number, mark: string) {
    let numStr: string = num.toString();
    let resultStr: string = '';
    while (numStr.length > 3) {
        resultStr = mark + numStr.slice(numStr.length - 3) + resultStr;
        numStr = numStr.slice(0, numStr.length - 3);
    }
    if (numStr.length > 0) {
        resultStr = numStr + resultStr;
    }
    return resultStr;
}

/**
 * 冒泡排序迭代写法。
 * @param arr 需要被排序的数组
 * @param comparer 比较器。
 */
function bubbleSort<T>(arr: T[], comparer: (pre: T, next: T) => number) {
    let length = arr.length;
    for (let i = length - 1; i > 0; --i) {
        for (let j = 0; j < i; ++j) {
            if (comparer(arr[j], arr[j + 1]) > 0) {
                let temp: T = arr[j + 1];
                arr[j + 1] = arr[j];
                arr[j] = temp;
            }
        }
    }
    return arr;
}

/**
 * 判断两个闭区间是否重叠。Math.min(end1,end2)>=Math.max(start1,start2)
 * @param a 区间1的左开始
 * @param b 区间1的右结束
 * @param c 区间2的左开始
 * @param d 区间2的右结束
 */
function isOverlap(a:number,b:number,c:number,d:number){
    if(Math.min(b,d)>=Math.max(a,c)){
        return true;
    }
    return false;
}

/**
 * 数组乱序。
 * @param arr 需要被数组乱序的数组 
 */
function mixin(arr: any[]) {
    let newArr: any[] = [];
    while (arr.length > 0) {
        let index = Math.floor(Math.random() * arr.length);
        newArr.push(arr[index]);
        arr.splice(index, 1)
    }
    return newArr;
}

export {
    debounce,
    throttle,
    easyDeepClone,
    deepClone,
    ajax,
    addMark,
    bubbleSort,
    mixin,
    isOverlap
}

